#include "threading_Lock.h"
#include "pika_platform_thread.h"





void threading_Lock___init__(PikaObj *self){
    pika_platform_thread_lock_t* m = pikaMalloc(sizeof(pika_platform_thread_lock_t));
    
    int err = pika_platform_thread_lock_init(m);
    if (err == PIKA_RES_ERR_MEMORY_ERROR){
        obj_raise(self, PIKA_RES_ERR_RUNTIME_ERROR, "malloc fail.");
        return;
    }
    obj_setPtr(self, "lock", m);
}

pika_bool threading_Lock_acquire(PikaObj *self, pika_bool block, Arg* timeout){
    pika_platform_thread_lock_t* m = obj_getPtr(self, "lock");

    ArgType timout_type = arg_getType(timeout);
    pika_float timeout_f;
    if (timout_type == ARG_TYPE_FLOAT){
        timeout_f = arg_getFloat(timeout);
        if (timeout_f < 0.0){
            obj_raise(self, PIKA_RES_ERR_VALUE_ERROR, "timeout shouldn't less than 0.");
            return pika_false;
        }
    }
    else if (timout_type == ARG_TYPE_INT){
        timeout_f = (pika_float)arg_getInt(timeout);
        if (timeout_f < 0.0){
            obj_raise(self, PIKA_RES_ERR_VALUE_ERROR, "timeout shouldn't less than 0.");
            return pika_false;
        }
    }
    else if (timout_type == ARG_TYPE_NONE){
        timeout_f = -1;
    }
    else{
        obj_raise(self, PIKA_RES_ERR_TYPE_ERROR, "float, int or None is required.");
        return pika_false;
    }

    int result = pika_platform_thread_lock_acquire(m, block, timeout_f);
    return result == 0 ? pika_true : pika_false;
}

pika_bool threading_Lock_is_locked(PikaObj *self){
    pika_platform_thread_lock_t* m = obj_getPtr(self, "lock");
    pika_GIL_EXIT();
    int result = pika_platform_thread_lock_locked(m);
    pika_GIL_ENTER();
    if (result == 0) {
        return pika_false; // 锁未被占用/*  */
    } else {
        // 锁已被占用或发生了其他错误
        return pika_true;
    }
}

void threading_Lock_release(PikaObj *self){
    pika_platform_thread_lock_t* m = obj_getPtr(self, "lock");
    if (pika_platform_thread_lock_release(m) < 0){
        obj_raise(self, PIKA_RES_ERR_RUNTIME_ERROR, "cannot release on un-acquired lock.");
        return;
    }
}

void threading_Lock___del__(PikaObj *self){
    pika_platform_thread_lock_t* m = obj_getPtr(self, "lock");
    pika_platform_thread_lock_destroy(m);
    pikaFree(m, sizeof(pika_platform_thread_lock_t));
}
